package com.gitee.huanminabc.utils_tools.redis.aspect.handler;

import com.gitee.huanminabc.utils_tools.redis.redisson.utils.RedissonLockUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * 分布式定时任务加锁
 * 在定时器执行之前,先执行锁,避免集群环境下,多个定时器同时执行
 */
@Aspect
@Component
@Slf4j
public class RedisScheduledClusterAspect {

    @Value("${spring.redis.scheduled-lock:false}")
    private boolean scheduledLock;

    @Autowired
    private RedissonLockUtil redissonLockUtil;

    //方法和类上的注解
    @Pointcut("@annotation(scheduled)")
    public void pointCut(Scheduled scheduled) {
    }

    @Around(value = "pointCut(scheduled)", argNames = "pjp,scheduled")
    public Object around(ProceedingJoinPoint pjp, Scheduled scheduled) throws Throwable {
        if (!scheduledLock) {
            return pjp.proceed();
        }
        //获取类.方法名
        String className = pjp.getTarget().getClass().getName();
        String methodName = pjp.getSignature().getName();
        String key = className + "::" + methodName ;

        redissonLockUtil.defaultTryLock(key,()->{
            try {
                pjp.proceed();
            } catch (Throwable throwable) {
                log.error("{}->定时任务执行失败", key, throwable);
            }
        });
        return null;
    }
}
